{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Part 1: Python Basics for Agent-Based Modelling\n",
    "\n",
    "##### Authors: Bill Thompson (biltho@mpi.nl) and Limor Raviv (limor.raviv@mpi.nl) \n",
    "Please let us know if you have any comments, suggestions or questions regarding this notebook.\n",
    "\n",
    "---------------\n",
    "\n",
    "## Summary\n",
    "In this first tutorial, we will introduce the Python commands needed for basic agent-based modelling: lists, loops, conditions and functions.\n",
    "Hopefully, you have managed to install Anaconda and open this file as an interactive jupyter notebook, and you can use Shift+Enter to run each code line. You can change the code yourself by editing each cell. A good exercise would be to run each cell first, and then add your own modifications to check that you've understood. \n",
    "\n",
    "-------------- \n",
    "\n",
    "\n",
    "### 1. Lists\n",
    "The first thing you need to know is how to make lists.\n",
    "\n",
    "Lists are created using square brackets. You can use lists to store many types of value: from numbers, to strings, to other lists. In fact, we will often use lists of lists to create our populations of agents."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "First, let's make an empty list and print it:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[]\n"
     ]
    }
   ],
   "source": [
    "emptylist = []\n",
    "\n",
    "print(emptylist)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now, let's make some lists with numbers!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3]\n"
     ]
    }
   ],
   "source": [
    "# Make a list of integers\n",
    "\n",
    "ints = [1,2,3]\n",
    "\n",
    "print(ints)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1.0, 2.0, 3]\n"
     ]
    }
   ],
   "source": [
    "# Make a list of floats by adding dots after the numbers\n",
    "# To see the crucial difference between floats and intgers, try dividing 5 / 2 and 5. / 2.\n",
    "\n",
    "nums = [1.,2.,3]\n",
    "\n",
    "print(nums)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can also make a list of numbers using \"range\"."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "NOTE: Python starts counting from zero, not one!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "See what this means for yourself by trying to generate a list with a range of 10."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n"
     ]
    }
   ],
   "source": [
    "# Make a with a range of 10 items - but pay attention!\n",
    "\n",
    "nums2 = range(10)\n",
    "\n",
    "print(list(nums2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can also make lists of random numbers within a given range using a package called \"random\":"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[15, -48, -32, -36, -50, 7, 1, -42, -6, 39]\n"
     ]
    }
   ],
   "source": [
    "import random \n",
    "\n",
    "length = 10\n",
    "\n",
    "randomlist = random.sample(range(-50, 50), length)\n",
    "\n",
    "print(randomlist)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Of course, lists don't have to contain numbers. You can also create lists of strings:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['my', 'cat', 'is', 'fluffy']\n"
     ]
    }
   ],
   "source": [
    "# Make a list of words\n",
    "\n",
    "mywordlist = ['my', 'cat', 'is', 'fluffy']\n",
    "\n",
    "print(mywordlist)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Or lists of lists:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[['my', 'cat', 'is', 'fluffy'], [1, 2, 3], ['dog', 'fish'], range(0, 2)]\n"
     ]
    }
   ],
   "source": [
    "# Create a list of lists\n",
    "\n",
    "superlist = [mywordlist, ints, ['dog', 'fish'], range(2)]\n",
    "\n",
    "print(superlist)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can also combine lists and add more values to them. Note that without assigning the output to a variable, it doesn't save the changes to the original list."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['my', 'cat', 'is', 'fluffy', 1, 2, 3]\n"
     ]
    }
   ],
   "source": [
    "# Combine lists and save to a new list\n",
    "\n",
    "mynewlist = mywordlist + ints\n",
    "\n",
    "print(mynewlist)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['Jane', 'said', 'my', 'cat', 'is', 'fluffy']"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Add values to the start of a list without changing the list or saving the output\n",
    "\n",
    "['Jane', 'said'] + mywordlist"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['my', 'cat', 'is', 'fluffy', 'too']"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Add values to the end of a list (again, without saving the changes)\n",
    "\n",
    "mywordlist + ['too']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['Jane', 'said', 'my', 'cat', 'is', 'fluffy']\n"
     ]
    }
   ],
   "source": [
    "# Add values to the start of a list and save changes\n",
    "#\n",
    "mysecondwordlist= ['Jane', 'said'] + mywordlist\n",
    "\n",
    "print(mysecondwordlist)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['my', 'cat', 'is', 'fluffy', 1, 2, 3, 4, 'This works!']\n"
     ]
    }
   ],
   "source": [
    "# Use \".append\" to add items to the end of a list and save changes\n",
    "\n",
    "mynewlist.append(4)\n",
    "mynewlist.append('This works!')\n",
    "\n",
    "print(mynewlist)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you want to retrieve a specific item from a list, you can use its index. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "But remember, Python starts counting from zero, not one!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This means that for a list of length *l*, the first value in the list is stored in position *0*, and the last values is stored in position *l-1*."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['my', 'cat', 'is', 'fluffy']\n",
      "This list is of length 4\n",
      "Cell 0 contains the word: my\n",
      "Cell 1 contains the word: cat\n",
      "Cell 2 contains the word: is\n",
      "Cell 3 contains the word: fluffy\n"
     ]
    }
   ],
   "source": [
    "# Check the indexing of a list\n",
    "print(mywordlist)\n",
    "print('This list is of length', len(mywordlist))\n",
    "print('Cell 0 contains the word:', mywordlist[0])\n",
    "print('Cell 1 contains the word:', mywordlist[1])\n",
    "print('Cell 2 contains the word:', mywordlist[2])\n",
    "print('Cell 3 contains the word:', mywordlist[3])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['your', 'cat', 'is', 'fluffy']\n"
     ]
    }
   ],
   "source": [
    "# Change a specific value in a list using its index\n",
    "\n",
    "mywordlist[0] = 'your'\n",
    "\n",
    "print(mywordlist)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. Loops\n",
    "The second thing you need to know is how to create For loops, with the same action repeated multiple time on different values. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Importantly, you need to use a colon at the end of every \"for\" statement, and use indentation to indicate which statments belong in the loop."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here are some basic exmaples:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "1\n",
      "2\n",
      "3\n",
      "4\n"
     ]
    }
   ],
   "source": [
    "# Make a loop that goes through all values in a given list and prints them\n",
    "\n",
    "for i in range(5):\n",
    "    print(i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "10\n",
      "11\n",
      "12\n",
      "13\n",
      "14\n"
     ]
    }
   ],
   "source": [
    "# Make a loop that adds 10 to every number in a given range and prints it\n",
    "\n",
    "for i in range(5):\n",
    "    print(i+10)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can loop over many things, as long as they have some values in them. For example:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.5\n",
      "4.0\n",
      "5.5\n",
      "11.0\n"
     ]
    }
   ],
   "source": [
    "# Looping over a list of numbers\n",
    "\n",
    "for i in [3.,8.,11.,22.]:\n",
    "    print(i/2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Jane\n",
      "said\n",
      "my\n",
      "cat\n",
      "is\n",
      "fluffy\n"
     ]
    }
   ],
   "source": [
    "# Looping over a list of numbers in a given size\n",
    "\n",
    "for i in range(len(mysecondwordlist)):\n",
    "    print(mysecondwordlist[i])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Jane\n",
      "said\n",
      "my\n",
      "cat\n",
      "is\n",
      "fluffy\n"
     ]
    }
   ],
   "source": [
    "# Looping over a list of strings\n",
    "\n",
    "for word in mysecondwordlist:\n",
    "    print(word)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And we can use loops to create and update lists:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0, 5, 10, 15]\n"
     ]
    }
   ],
   "source": [
    "# Make a loop that adds values to a list\n",
    "\n",
    "looplist = [] # if you don't have an existing list already, you'll need to define an empty list first \n",
    "\n",
    "for i in range(4):\n",
    "    looplist.append(i*5)\n",
    "\n",
    "print(looplist)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0, 500, 1000, 1500, 'your', 'cat', 'is', 'fluffy']\n"
     ]
    }
   ],
   "source": [
    "# Make another loop that multiples the numbers by 100 and adds the corresponding string from a different list\n",
    "\n",
    "for i in range(len(looplist)):\n",
    "    looplist[i] = looplist[i] * 100\n",
    "    looplist.append(mywordlist[i])\n",
    "\n",
    "print(looplist)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. Conditions\n",
    "The third thing you need to know is how to create If statments, so that different actions can be taken in different conditions."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here you'll also need to use a colon at the end of every if/else statement, and use indentation to indicate which statments belong in the condition."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "First, you can make a basic statment with one condition:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x is bigger than 3\n"
     ]
    }
   ],
   "source": [
    "x = 4\n",
    "\n",
    "if x > 3:\n",
    "    print(\"x is bigger than 3\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you want to have a different action taken when this condition is false, you can use \"else\":"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "y is smaller than 3\n"
     ]
    }
   ],
   "source": [
    "y = 2\n",
    "\n",
    "if y > 3:\n",
    "    print(\"y is bigger than 3\")\n",
    "else:\n",
    "    print(\"y is smaller than 3\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For more conditions, use \"elif\" (short for 'else if'):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x equals 4\n"
     ]
    }
   ],
   "source": [
    "# Now, let's put more conditions in there\n",
    "\n",
    "x = 4\n",
    "\n",
    "if x > 7:\n",
    "    print(\"x is bigger than 7\")\n",
    "elif x > 6:\n",
    "    print(\"x is bigger than 6\")\n",
    "elif x > 5:\n",
    "    print(\"x is bigger than 5\")\n",
    "elif x == 4:\n",
    "    print(\"x equals 4\")\n",
    "else:\n",
    "    print(\"x is smaller than 4\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Of course, you can combine loops and if statments to do some more intersting things:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "the number 0 is smaller than 5\n",
      "the number 1 is smaller than 5\n",
      "the number 2 is smaller than 5\n",
      "the number 3 is smaller than 5\n",
      "the number 4 is smaller than 5\n",
      "the number 5 equals 5 (sanity check!)\n",
      "the number 6 is bigger than 5\n",
      "the number 7 is bigger than 5\n",
      "the number 8 is bigger than 5\n",
      "the number 9 is bigger than 5\n"
     ]
    }
   ],
   "source": [
    "for number in range(10):\n",
    "    if number < 5:\n",
    "        print('the number', number, 'is smaller than 5')\n",
    "    elif number==5:\n",
    "        print('the number', number, 'equals 5 (sanity check!)')\n",
    "    else:\n",
    "        print('the number', number, 'is bigger than 5')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Like only apply operations on certain types of values in the list:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "my\n",
      "cat\n",
      "is\n",
      "fluffy\n",
      "... this is not a word\n",
      "... this is not a word\n",
      "... this is not a word\n",
      "... this is not a word\n",
      "This works!\n"
     ]
    }
   ],
   "source": [
    "for word in mynewlist:\n",
    "    if type(word)== int:\n",
    "        print('... this is not a word')\n",
    "    else:\n",
    "        print(word)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4. Functions\n",
    "The last thing you need to know is how to write and call functions."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Functions are created using \"def\", and typically return some value. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here are some basic examples to help you get started!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "100"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Create a function called \"func\" that adds 1 to a given number i\n",
    "\n",
    "def func(i):\n",
    "    return i + 1\n",
    "\n",
    "# Call the function on a specific number\n",
    "\n",
    "func(99)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, 4, 6, 8]"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Create a function called \"myfunc\" that multiplies a list of numbers by 2\n",
    "\n",
    "def myfunc(numlist):\n",
    "    newvalues = []\n",
    "    for i in numlist:\n",
    "        newvalues.append(i*2)                    \n",
    "    return newvalues\n",
    "\n",
    "# Call the function on a myfuspecific list\n",
    "\n",
    "myfunc([1,2,3,4])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'cat'"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Define a function called \"listfunc\" that returns the value in the third cell of any list\n",
    "\n",
    "def listfunc(mylist):\n",
    "    if len(mylist) >= 4:\n",
    "        return mylist[3]\n",
    "    else:\n",
    "        return 'your list is not long enough'\n",
    "    \n",
    "\n",
    "# Call the function on one of our lists\n",
    "\n",
    "listfunc(mysecondwordlist)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can also save the function's output to a variable:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]\n"
     ]
    }
   ],
   "source": [
    "results = myfunc(range(10))\n",
    "\n",
    "print(results)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If your function has more than one returned output, you can save both using a comma:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[5, 10, 15, 20]\n",
      "12.5\n"
     ]
    }
   ],
   "source": [
    "# Create a function called \"twofunc\" that gives back two things\n",
    "\n",
    "def twofunc(anotherlist):\n",
    "    values1 = []\n",
    "    for i in anotherlist:\n",
    "        values1.append(i*5)                    \n",
    "    mean = sum(values1)/len(values1)\n",
    "    return values1, mean\n",
    "\n",
    "# Call the function on a myfuspecific list\n",
    "\n",
    "output1, output2 = twofunc([1,2,3,4])\n",
    "\n",
    "print(output1)\n",
    "print(output2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Excellent! Now you're really ready to start modelling!"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.4.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
